#include <iostm8s103f3.h>

// unlock flash: 0 for eeprom and 1 for flash
void FLASH_Unlock(unsigned char FLASH_MemType)
{
  if(FLASH_MemType == 1) {  // Unlock program memory
    FLASH_PUKR = 0x56;
    FLASH_PUKR = 0xAE;
  }
  else {  // Unlock data memory
    FLASH_DUKR = 0xAE;
    FLASH_DUKR = 0x56;
  }
}

// lock flash: 0 for eeprom and 1 for flash
void FLASH_Lock(unsigned char FLASH_MemType)
{
  if(FLASH_MemType == 1) {  // lock program memory
    FLASH_IAPSR &= (unsigned char)0xFD;
  }
  else {  // lock data memory
    FLASH_IAPSR &= (unsigned char)0xF7;
  }
}

// read one byte
unsigned char FLASH_ReadByte(unsigned int Address)
{
  return (*(__near unsigned char *)Address); 
}

// program one byte
void FLASH_ProgramByte(unsigned int Address, unsigned char Data)
{
  *(__near unsigned char*)Address = Data;
}

// erase one byte
void FLASH_EraseByte(unsigned int Address)
{
  *(__near unsigned char*)Address = 0x00; 
}

void main(void)
{
  unsigned char val = 0x00;
  unsigned char val_comp = 0x00;
  unsigned int add = 0x8242;
  unsigned char error = 0;

  CLK_CKDIVR &= (unsigned char)(~0x18);  // 16MHz high speed internal clock

  FLASH_Unlock(1);  // Unlock program memory

  val = FLASH_ReadByte(add);  // read a byte
  val_comp = (unsigned char)(~val);
  FLASH_ProgramByte((add + 1), val_comp);  // program a byte
  // verify read and write
  val = FLASH_ReadByte((add + 1));
  if (val != val_comp)
    error |= 0x01;

  // write a new value again
  FLASH_ProgramByte((add + 1), 0x11);  // program a byte
  val = 0;
  val = FLASH_ReadByte((add + 1));
  if (val != 0x11)
    error |= 0x02;
  
  // erase 2 bytes
  FLASH_EraseByte(add);
  FLASH_EraseByte((add + 1));
  val = FLASH_ReadByte(add);
  val_comp = FLASH_ReadByte((add + 1));
  if ((val != 0x00) & (val_comp != 0x00))
    error |= 0x04;
  
  while (1) {
  }
}
